/* 
 *  Copyright (c) 2011—2013 Panguso.com. All rights reserved. 
 *  File Name:  XESRandomReader_1 .java                                      
 *  File Contents Outline :  XES随机读取器
 *  File  Create Date:   2012年7月30日
 *  File Version#: Revision#: #1                  
 *  File  Latest Modify Date : 2013年1月16日
 *  File Author :  bachuan@panguso.com
 */
package cn.edu.thu.log.xes;
import java.io.*;
import java.util.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;


import org.deckfour.xes.factory.XFactory;
import org.deckfour.xes.factory.XFactoryRegistry;
import org.deckfour.xes.in.XParser;
import org.deckfour.xes.in.XParserRegistry;
import org.deckfour.xes.model.XLog;
import org.w3c.dom.Document;

import org.xml.sax.InputSource;
import storage.dbhelper.XESHelper;
import storage.dbobject.DbXES;

public class XESRandomReader_1 implements XESReaderInterface {

    DbXES currentXES;
    String sourchPath;
    String name;
    double proportion;
    XLog log;
    int currentIndex;
    XESHelper xesh;
    List<DbXES> xesList;
    Hashtable<String, Integer> branchInfoMap;
    String branchList;
    ArrayList<Float> proportionList;
    int totalBranchNum;
    int branchNum;
    int resultBranchNum;
    ArrayList<String> alreadyChosenList;

    public XESRandomReader_1() {
        System.out.println("XESRandomReader()");
        XFactory factory = XFactoryRegistry.instance().currentDefault();
        log = factory.createLog();
        currentIndex = 0;
        xesh = new XESHelper();
        proportion = 0.1;
        branchInfoMap = new Hashtable<String, Integer>();
        proportionList = new ArrayList<Float>();
        alreadyChosenList = new ArrayList<String>();
    }

//    public void setUpXESPara(String sourcePath, String name) {
//        this.sourchPath = sourcePath;
//        this.name = name;
//        File readFile = new File(sourcePath);
//        getFilesize(readFile);
//        System.out.print("\nthere are xes files:" + size);
//    }
    @Override
    public void setUpXESPara(String name) {

        this.name = name;
        proportionList = new ArrayList<Float>();
        branchInfoMap = xesh.getSameNameNum(DbXES.cl_name, name);

        Enumeration keyEnu = branchInfoMap.keys();
        totalBranchNum = 0;
        branchNum = 0;
        while (keyEnu.hasMoreElements()) {
            String eachBranchName = keyEnu.nextElement().toString();
            System.out.println("eachBranchName:" + eachBranchName);
            totalBranchNum = totalBranchNum + branchInfoMap.get(eachBranchName);
            System.out.println("totalBranchNum:" + totalBranchNum);
            branchNum++;
        }
        for (float i = 1; i <= totalBranchNum; i++) {

            proportionList.add((i / new Float(totalBranchNum)));
        }
        System.out.println("totalBranchNum:" + totalBranchNum);
    }

    @Override
	public ArrayList<Float> gerRandomList() {
        // System.out.println("proportion:" + proportionList);
        return proportionList;
    }

    @Override
	public void setUpRandomProportion(double proportion) {
        proportion = proportion;
        System.out.println("proportion:" + proportion);

        resultBranchNum = (int) (proportion * totalBranchNum);
        //  System.out.println("resultBranchNum:" + resultBranchNum);
        currentIndex = 0;
        if (resultBranchNum == 0) {
            System.out.println("resultBranchNum=0:" + totalBranchNum);
            resultBranchNum = 1;
        }
        System.out.println("resultBranchNum:" + resultBranchNum);
        generateRandomList();
        System.out.println("alreadyChosenList:" + alreadyChosenList);
//        getFilesize();
//        System.out.print("\nthere are xes files:" + size);
    }

    private void generateRandomList() {
        while (alreadyChosenList.size() < resultBranchNum) {
            System.out.println("alreadyChosenList.size():" + alreadyChosenList.size());
            int randomBranch = (int) (Math.random() * branchNum);
            List<DbXES> randomXESList = xesh.getXESsByNameBranch(DbXES.cl_name, name, DbXES.cl_branch, String.valueOf(randomBranch));
            int randomXESListSize = randomXESList.size();
            randomXESList = null;
            if (randomXESListSize > 0) {
                int listSize = randomXESListSize;
                int randomIndexInList = (int) (Math.random() * (listSize - 1));
                if (!alreadyChosenList.contains(randomBranch + "_" + randomIndexInList)) {
                    //   currentXES = randomXESList.get(randomIndexInList);
                    alreadyChosenList.add(randomBranch + "_" + randomIndexInList);
                    System.out.println("addToExist:" + randomBranch + "_" + randomIndexInList);
                } else {
//                    generateRandomList();
                }
            }
        }

    }

    @Override
    public boolean hadNext() {
        if (currentIndex < alreadyChosenList.size()) {
            String currentIndexInfo = alreadyChosenList.get(currentIndex);
            String[] currentIndexInfos = currentIndexInfo.split("_");
            String currentBranch = currentIndexInfos[0];
            System.out.println("currentIndexInfo:" + currentIndexInfo);
            String currentIndexString = currentIndexInfos[1];
            int currentIndex = Integer.parseInt(currentIndexString);
            List<DbXES> currentXESList = xesh.getXESsByNameBranch(DbXES.cl_name, name, DbXES.cl_branch, currentBranch);
            currentXES = currentXESList.get(currentIndex);

            return true;
        } else {
            currentIndex = 0;//add
            return false;
        }

    }

    @Override
    public XLog Next() throws Exception {
//        List<DbXES> list = xesh.getXESs(DbXES.cl_name, name);
        DbXES xes = currentXES;

        if (xes != null) {
            System.out.println("currentXES:Name():" + currentXES.getName() + " Branch:" + currentXES.getBranch() + " currentIndex:" + currentIndex);
            //change xmlString to Document
            String xmlString = xes.getXES();
            //System.out.println("xmlString:"+xmlString);
            StringReader sr = new StringReader(xmlString);
            InputSource is = new InputSource(sr);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(is);


            //change Document to .xes File
            File tempFile = new File("D:\\temp.xes");
            TransformerFactory tfactory = TransformerFactory.newInstance();
            Transformer transformer = tfactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(tempFile);
            transformer.transform(source, result);

            //read .XES file to XLog
            readOneXESToLog(tempFile);
            tempFile.delete();

        } else {
            // System.out.println("\ndidnot find xes:"+name+" currentIndex:"+currentIndex+" currentIndexInCurrentList:"+currentIndexInCurrentList);
        }
        return log;
    }

    /**
     * read logs in standard format file
     *
     * @param standardLogFile the absolute path of xes file
     * @return collections of XLog
     */
    private void readOneXESToLog(File sourceFile) {
        XFactory factory = XFactoryRegistry.instance().currentDefault();
        log = factory.createLog();
        // load source file
        Collection<XLog> logs = null;
        try {
            for (XParser parser : XParserRegistry.instance().getAvailable()) {
                if (parser.canParse(sourceFile)) {
                    // System.out.println("Using input parser: " + parser.name());
                    logs = parser.parse(sourceFile);

                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (XLog eachLog : logs) {
            log.addAll(eachLog);

        }
        currentIndex++;

    }

    @Override
	public DbXES NextXES() {
        DbXES xes = currentXES;

        if (xes != null) {
            System.out.println("currentXES:Name():" + currentXES.getName() + " Branch:" + currentXES.getBranch() + " currentIndex:" + currentIndex);
        }
        return xes;
    }
}